package com.mazaiting.generator.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mazaiting.web.wrapper.WrappedHttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * 日志过滤器
 */
@Slf4j
@Order(value = -2)
@WebFilter(filterName = "logFilter", urlPatterns = "/*")
public class LogFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain filterChain) throws ServletException, IOException {

        log.info("========= LogFilter-start =========");
        HttpServletRequest req = (HttpServletRequest) request;
        String uri = req.getRequestURI();
        // 内容类型
        String contentType = req.getContentType();
        // 请求方法
        String method = req.getMethod();
        // 内容类型为空且为get请求
        if (!StringUtils.hasLength(contentType) && HttpMethod.GET.matches(method)){
            filterChain.doFilter(request, response);
        } else {
            // json 格式转换
            WrappedHttpServletRequest proxyReq = new WrappedHttpServletRequest(req);
            // 请求体
            String requestBody = proxyReq.getRequestBody();
            log.info("请求地址: {}, 查询参数: {}, 请求参数: {}", uri, proxyReq.getQueryString(), requestBody);

            // 响应包装
            ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) response);
            filterChain.doFilter(proxyReq, responseWrapper);
            // 获取结果
            String result = new String(responseWrapper.getResponseData());
            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.write(result.getBytes());
            outputStream.flush();
            outputStream.close();

            log.info("响应地址: {}, 响应内容: {}", uri, result);
        }
        log.info("========= LogFilter-end =========");
    }

    /**
     * 转换 map
     *
     * @param req 请求
     * @return 多值 map
     */
    private MultiValueMap<String, Object> convert(HttpServletRequest req) {
        Map<String, String[]> parameterMap = req.getParameterMap();
        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        // 判断参数是否为空
        if (ObjectUtils.isEmpty(parameterMap)) {
            return map;
        }

        for (Entry<String, String[]> entry : parameterMap.entrySet()) {
            String key = entry.getKey();
            String[] strArr = entry.getValue();
            // roleIds.0 转换为 roleIds[0]
            if (key.contains(".")) {
                // 第 0 位是 key, 第 1 位是索引位置
                String[] keyArr = key.split("\\.");
                // 索引
                int index = Integer.parseInt(keyArr[1]);
                String tmpKey = keyArr[0];
                String tmpValue = strArr[0];
//                map.add(tmpKey + "[" + index + "]", tmpValue);
                // 解决方法参数使用@RequestParam异常
                List<Object> objects = map.getOrDefault(tmpKey, new ArrayList<>());
                objects.add(index, tmpValue);
                map.put(tmpKey, objects);
            } else {
                String s = strArr[0];
                map.add(key, s);
            }
        }
        return map;
    }

    /**
     * 转换数据
     *
     * @param data 数据
     * @return 多值 map
     */
    private MultiValueMap<String, Object> convert(String data) {
        return convertJson(data);
    }

    /**
     * 将 JSON 字符串转换为 map
     *
     * @param inputString 字符串
     * @return 多值 map
     */
    private MultiValueMap<String, Object> convertJson(String inputString) {

        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        // 判断参数是否为空
        if (ObjectUtils.isEmpty(inputString)) {
            return map;
        }

        JSONObject obj = JSON.parseObject(inputString);
        for (Entry<String, Object> entry : obj.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (value instanceof JSONArray arr) {
                // 判断元素是否为对象
                Object v = arr.get(0);
//                if (v instanceof JSONObject) {
//                    map.addAll(key, arr);
//                } else {
                // 修复无法传递数组的问题
                for (int i = 0; i < arr.size(); i++) {
                    // 使用roleIds[0] - value的形式转换
                    map.add(key + "[" + i + "]", arr.get(i));
                }
//                }
            } else {
                map.add(key, value);
            }
        }
        return map;
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }


    @Override
    public void destroy() {
    }
}
